// 获取配置并且解析配置
import controConfig from './init/controConfig'

import configs from './init/config'
// 初始化一些配置
import './init/main'
import http from "http"
import inlet from './entrance/inlet'
import run_route from './kernel/route/pars_route'
import auto_load_interface from './kernel/auto_load/auto_load'
import monitor from './kernel/monitor/Monitor'
import Route from './kernel/route/route'
import tools from './kernel/tools/tools'
import color from './kernel/tools/color';
import sugar from './kernel/tools/sugar';
import cross from "./plug-in/crossDomain";
import auto_load_route from "./annotation/auto_load_route"
// 捕捉未被处理的全局异常
process.on("uncaughtException",err=>{
    handleExceptions({},err);
})

import { controller, middleware, cgem } from './gem';
import handleExceptions from './entrance/specialInterface/handleExceptions'

let startRun:Array<Function> = [];
let endRun:Array<Function> = [()=>{
    // 更新下本地ip
    cross.update_local_ip();
}];

// 加载一下路由，这样用户可以直接用.get.post
let route = new Route({id:__filename})
// export let auto_load = auto_load_route;

class index implements cgem{
    cross: any = cross;
    public config = configs;
    public auto_load = auto_load_route;

    /** 创建路由 */
    public createRoute (){return new Route(sugar.super_path(2,true))}

    //启动框架服务
    public async start(config:any,host?:string,callback?:Function,add?:boolean){
        for(let e of startRun){await e()}
        if(typeof config === "object"){
            config.host && (controConfig.setServers("host",config.host))
            config.port && (controConfig.setServers("port",Number(config.port)))
            controConfig.setServers("callback",host)
            controConfig.setServers("add",callback);
        }else if(typeof config === "function"){
            // 只有回调
            controConfig.setServers("callback",config);
            controConfig.setServers("add",host);
        }else if(host){
            controConfig.setServers("host",host)
            controConfig.setServers("port",Number(config))
            controConfig.setServers("callback",callback)
            controConfig.setServers("add",add);
        }
        //初始化一些数据
        this.init().then(_=> {
            controConfig.setServers("port",Number(controConfig.getServers("port")));
            // ===================================================启动服务,并且加载入口文件
            const server = http.createServer(inlet);
            server.listen(controConfig.getServers("port") as number, controConfig.getServers("host") as string,()=>ts(controConfig.getServers("callback") as Function));
            server.on("error", () => {
                console.log(`${color("灰色",controConfig.getServers("port"))} 端口被占用,改端口为 ${color("绿色",controConfig.getServers("port") as number + 1)}`)
                controConfig.setServers("port",controConfig.getServers("port") as number + 1);
                server.listen(controConfig.getServers("port"));
            });
        }).catch(err=>{
            console.log(err)
        });
    }

    // 添加项目需要使用到的模块
    public use(plug:middleware):void{
        //加载的组件 进全局中间件
        controConfig.addPlug((plug as any)?.default || plug)
    }
    public useGlobal(data:any):void{this.config.addGlobalMiddleware(data)}

    // 路由转发一下 过一段时间我不看估计我都看不懂
    public get(url:string,fun:controller|string):{midd:Function}{return route.get(url,(typeof fun==='string' && fun.startsWith("."))?"../"+fun:fun)}
    public post(url:string,fun:controller|string):{midd:Function}{return route.post(url,(typeof fun==='string' && fun.startsWith("."))?"../"+fun:fun);}
    public put(url:string,fun:controller|string):{midd:Function}{return route.put(url,(typeof fun==='string' && fun.startsWith("."))?"../"+fun:fun);}
    public delete(url:string,fun:controller|string):{midd:Function}{return route.delete(url,(typeof fun==='string' && fun.startsWith("."))?"../"+fun:fun);}
    public any(url:string,fun:controller|string):{midd:Function}{return route.any(url,(typeof fun==='string' && fun.startsWith("."))?"../"+fun:fun);}

    public $404(fun:controller):{midd(...arg0: any[]):void}{return route.$404(fun);}
    public $500(fun:controller):{midd(...arg0: any[]):void}{return route.$500(fun);}
    public $public(fun:controller){return route.$public(fun);}
    public $requestRecord(fun:controller):{midd(...arg0: any[]):void}{return route.$requestRecord(fun);}
    public $requestParse(fun:controller):{midd(...arg0: any[]):void}{return route.$requestParse(fun);}
    public start_run(fun:Function){startRun.push(fun)}
    public end_run(fun:Function){endRun.push(fun)}


    //初始化模块 以及环境
    public async init(){
        // 运行注解 必须先运行注解，不然靠注解生成的注解模块就会无法使用
        controConfig.getAddress("middleware") &&
        controConfig.addrunAnnotation(controConfig.getAddress("middleware"));
        controConfig.getAddress("controller") &&
        controConfig.addrunAnnotation(controConfig.getAddress("controller"));
        // 运行注解
        await auto_load_interface(controConfig.getrunAnnotation());

        // 解析路由
        await run_route.start();

        // 启动热部署
        await monitor({
            // 控制器热部署
            Controller:controConfig.getAddress("controller"),
            // 路由文件热部署
            route_arr: controConfig.getrouteConfig().map(e=>e.path),
            // 监控注解
            annotation:controConfig.getrunAnnotation()
        },controConfig.getFeatures("hotDeployment"));
    }

}
let app:cgem = new index();
module.exports = app;


//提示
async function ts(callback?:Function){
    if(global.web_status === undefined){
        for(let f of endRun){await f()}
        // 置顶一下
        global.web_status=true;
        loader("./init/banner")

        let IP:any = tools.local_ip();
        if(controConfig.getServers("add") || !callback){
            console.log(color("青色","\nCGEM框架运行成功,请使用以下网址访问网站"));
            if(controConfig.getServers("host") === "0.0.0.0"){
                Object.keys(IP).forEach(ip=>{
                    console.log(color("绿色",`Server running at `+color("蓝色",`http://${IP[ip].address+":"+controConfig.getServers("port")}/`)));
                })
            }else{
                console.log(color("绿色",`Server running at http://${controConfig.getServers("host")}:${controConfig.getServers("port")}/`));
            }
        }
        callback && callback(IP,controConfig.getServers("port"))
        console.log();
    }
}

// set-ExecutionPolicy RemoteSigned
/**
git config --global user.email "2844087515@qq.com"
git config --global user.name "baige" 
 */